home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume90 / aplictns / xscheme2 / part05 < prev    next >
Internet Message Format  |  1990-04-14  |  37KB

  1. Path: xanth!cs.odu.edu!Amiga-Request
  2. From: Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v90i143: XScheme 0.20 - an object-oriented scheme, Part05/07
  5. Message-ID: <12213@xanth.cs.odu.edu>
  6. Date: 14 Apr 90 21:12:44 GMT
  7. Sender: tadguy@cs.odu.edu
  8. Reply-To: rusty@fe2o3.UUCP (Rusty Haddock)
  9. Lines: 1499
  10. Approved: tadguy@cs.odu.edu (Tad Guy)
  11. X-Mail-Submissions-To: Amiga@cs.odu.edu
  12. X-Post-Discussions-To: comp.sys.amiga
  13.  
  14. Submitted-by: rusty@fe2o3.UUCP (Rusty Haddock)
  15. Posting-number: Volume 90, Issue 143
  16. Archive-name: applications/xscheme-0.20/part05
  17.  
  18. #!/bin/sh
  19. # This is a shell archive.  Remove anything before this line, then unpack
  20. # it by saving it into a file and typing "sh file".  To overwrite existing
  21. # files, type "sh file -c".  You can also feed this as standard input via
  22. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  23. # will see the following message at the end:
  24. #        "End of archive 5 (of 7)."
  25. # Contents:  Src/xscom.c
  26. # Wrapped by tadguy@xanth on Sat Apr 14 17:07:28 1990
  27. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  28. if test -f 'Src/xscom.c' -a "${1}" != "-c" ; then 
  29.   echo shar: Will not clobber existing file \"'Src/xscom.c'\"
  30. else
  31. echo shar: Extracting \"'Src/xscom.c'\" \(33402 characters\)
  32. sed "s/^X//" >'Src/xscom.c' <<'END_OF_FILE'
  33. X/* xscom.c - a simple scheme bytecode compiler */
  34. X/*    Copyright (c) 1988, by David Michael Betz
  35. X    All Rights Reserved
  36. X    Permission is granted for unrestricted non-commercial use    */
  37. X
  38. X#include "xscheme.h"
  39. X#include "xsbcode.h"
  40. X
  41. X/* size of code buffer */
  42. X#define CMAX    4000
  43. X
  44. X/* continuation types */
  45. X#define C_RETURN    -1
  46. X#define C_NEXT        -2
  47. X
  48. X/* macro to check for a lambda list keyword */
  49. X#define lambdakey(x)    ((x) == lk_optional || (x) == lk_rest)
  50. X
  51. X/* external variables */
  52. Xextern LVAL lk_optional,lk_rest,true;
  53. X
  54. X/* local variables */
  55. Xstatic LVAL info;        /* compiler info */
  56. X
  57. X/* code buffer */
  58. Xstatic unsigned char cbuff[CMAX];    /* base of code buffer */
  59. Xstatic int cbase;            /* base for current function */
  60. Xstatic int cptr;            /* code buffer pointer */
  61. X
  62. X/* forward declarations */
  63. Xint do_define(),do_set(),do_quote(),do_lambda(),do_delay();
  64. Xint do_let(),do_letrec(),do_letstar(),do_cond(),do_and(),do_or();
  65. Xint do_if(),do_begin(),do_while(),do_access();
  66. XLVAL make_code_object();
  67. X
  68. X/* integrable function table */
  69. Xtypedef struct { char *nt_name; int nt_code,nt_args; } NTDEF;
  70. Xstatic NTDEF *nptr,ntab[] = {
  71. X    "ATOM",            OP_ATOM,    1,
  72. X    "EQ?",            OP_EQ,        2,
  73. X    "NULL?",        OP_NULL,    1,
  74. X    "NOT",            OP_NULL,    1,
  75. X    "CONS",            OP_CONS,    2,
  76. X    "CAR",            OP_CAR,        1,
  77. X    "CDR",            OP_CDR,        1,
  78. X    "SET-CAR!",        OP_SETCAR,    2,
  79. X    "SET-CDR!",        OP_SETCDR,    2,
  80. X    "+",            OP_ADD,        -2,
  81. X    "-",            OP_SUB,        -2,
  82. X    "*",            OP_MUL,        -2,
  83. X    "QUOTIENT",        OP_QUO,        -2,
  84. X    "<",            OP_LSS,        -2,
  85. X    "=",            OP_EQL,        -2,
  86. X    ">",            OP_GTR,        -2,
  87. X    0
  88. X};
  89. X
  90. X/* special form table */
  91. Xtypedef struct { char *ft_name; int (*ft_fcn)(); } FTDEF;
  92. Xstatic FTDEF ftab[] = {
  93. X    "QUOTE",    do_quote,
  94. X    "LAMBDA",    do_lambda,
  95. X    "DELAY",    do_delay,
  96. X    "LET",        do_let,
  97. X    "LET*",        do_letstar,
  98. X    "LETREC",    do_letrec,
  99. X    "DEFINE",    do_define,
  100. X    "SET!",        do_set,
  101. X    "IF",        do_if,
  102. X    "COND",        do_cond,
  103. X    "BEGIN",    do_begin,
  104. X    "SEQUENCE",    do_begin,
  105. X    "AND",        do_and,
  106. X    "OR",        do_or,
  107. X    "WHILE",    do_while,
  108. X    "ACCESS",    do_access,
  109. X    0
  110. X};
  111. X
  112. X/* xlcompile - compile an expression */
  113. XLVAL xlcompile(expr,ctenv)
  114. X  LVAL expr,ctenv;
  115. X{
  116. X    /* initialize the compile time environment */
  117. X    info = cons(NIL,NIL); cpush(info);
  118. X    rplaca(info,newframe(ctenv,1));
  119. X    rplacd(info,cons(NIL,NIL));
  120. X
  121. X    /* setup the base of the code for this function */
  122. X    cbase = cptr = 0;
  123. X
  124. X    /* setup the entry code */
  125. X    putcbyte(OP_FRAME);
  126. X    putcbyte(1);
  127. X
  128. X    /* compile the expression */
  129. X    do_expr(expr,C_RETURN);
  130. X
  131. X    /* build the code object */
  132. X    settop(make_code_object(NIL));
  133. X    return (pop());
  134. X}
  135. X
  136. X/* xlfunction - compile a function */
  137. XLVAL xlfunction(fun,fargs,body,ctenv)
  138. X  LVAL fun,fargs,body,ctenv;
  139. X{
  140. X    /* initialize the compile time environment */
  141. X    info = cons(NIL,NIL); cpush(info);
  142. X    rplaca(info,newframe(ctenv,1));
  143. X    rplacd(info,cons(NIL,NIL));
  144. X
  145. X    /* setup the base of the code for this function */
  146. X    cbase = cptr = 0;
  147. X
  148. X    /* compile the lambda list and the function body */
  149. X    parse_lambda_list(fargs,body);
  150. X    do_begin(body,C_RETURN);
  151. X
  152. X    /* build the code object */
  153. X    settop(make_code_object(fun));
  154. X    return (pop());
  155. X}
  156. X
  157. X/* do_expr - compile an expression */
  158. XLOCAL do_expr(expr,cont)
  159. X  LVAL expr; int cont;
  160. X{
  161. X    LVAL fun;
  162. X    if (consp(expr)) {
  163. X    fun = car(expr);
  164. X     if (!symbolp(fun) || (!in_ntab(expr,cont) && !in_ftab(expr,cont)))
  165. X        do_call(expr,cont);
  166. X    }
  167. X    else if (symbolp(expr))
  168. X    do_identifier(expr,cont);
  169. X    else
  170. X    do_literal(expr,cont);
  171. X}
  172. X
  173. X/* in_ntab - check for a function in ntab */
  174. XLOCAL int in_ntab(expr,cont)
  175. X  LVAL expr; int cont;
  176. X{
  177. X    unsigned char *pname;
  178. X    pname = getstring(getpname(car(expr)));
  179. X    for (nptr = ntab; nptr->nt_name; ++nptr)
  180. X    if (strcmp(pname,nptr->nt_name) == 0) {
  181. X        do_nary(nptr->nt_code,nptr->nt_args,expr,cont);
  182. X        return (TRUE);
  183. X    }
  184. X    return (FALSE);
  185. X}
  186. X
  187. X/* in_ftab - check for a function in ftab */
  188. XLOCAL int in_ftab(expr,cont)
  189. X  LVAL expr; int cont;
  190. X{
  191. X    unsigned char *pname;
  192. X    FTDEF *fptr;
  193. X    pname = getstring(getpname(car(expr)));
  194. X    for (fptr = ftab; fptr->ft_name; ++fptr)
  195. X    if (strcmp(pname,fptr->ft_name) == 0) {
  196. X        (*fptr->ft_fcn)(cdr(expr),cont);
  197. X        return (TRUE);
  198. X    }
  199. X    return (FALSE);
  200. X}
  201. X
  202. X/* do_define - handle the (DEFINE ... ) expression */
  203. XLOCAL do_define(form,cont)
  204. X  LVAL form; int cont;
  205. X{
  206. X    if (atom(form))
  207. X    xlerror("expecting symbol or function template",form);
  208. X    define1(car(form),cdr(form),cont);
  209. X}
  210. X
  211. X/* define1 - helper routine for do_define */
  212. XLOCAL define1(list,body,cont)
  213. X  LVAL list,body; int cont;
  214. X{
  215. X    LVAL fargs;
  216. X    int off;
  217. X
  218. X    /* handle nested definitions */
  219. X    if (consp(list)) {
  220. X    cpush(cons(xlenter("LAMBDA"),NIL));    /* (LAMBDA) */
  221. X    rplacd(top(),cons(cdr(list),NIL));    /* (LAMBDA args) */
  222. X    rplacd(cdr(top()),body);        /* (LAMBDA args body) */
  223. X    settop(cons(top(),NIL));        /* ((LAMBDA args body)) */
  224. X    define1(car(list),top(),cont);
  225. X    drop(1);
  226. X    }
  227. X    
  228. X    /* compile procedure definitions */
  229. X    else {
  230. X
  231. X    /* make sure it's a symbol */
  232. X    if (!symbolp(list))
  233. X        xlerror("expecting a symbol",list);
  234. X
  235. X    /* check for a procedure definition */
  236. X    if (consp(body)
  237. X        &&  consp(car(body))
  238. X        &&  car(car(body)) == xlenter("LAMBDA")) {
  239. X        fargs = car(cdr(car(body)));
  240. X        body = cdr(cdr(car(body)));
  241. X        cd_fundefinition(list,fargs,body);
  242. X    }
  243. X
  244. X    /* compile the value expression or procedure body */
  245. X    else
  246. X        do_begin(body,C_NEXT);
  247. X    
  248. X    /* define the variable value */
  249. X    if (findcvariable(list,&off))
  250. X        cd_evariable(OP_ESET,0,off);
  251. X    else
  252. X        cd_variable(OP_GSET,list);
  253. X    do_literal(list,cont);
  254. X    }
  255. X}
  256. X
  257. X/* do_set - compile the (SET! ... ) expression */
  258. XLOCAL do_set(form,cont)
  259. X  LVAL form; int cont;
  260. X{
  261. X    if (atom(form))
  262. X    xlerror("expecting symbol or ACCESS form",form);
  263. X    else if (symbolp(car(form)))
  264. X    do_setvar(form,cont);
  265. X    else if (consp(car(form)))
  266. X    do_setaccess(form,cont);
  267. X    else
  268. X    xlerror("expecting symbol or ACCESS form",form);
  269. X}
  270. X
  271. X/* do_setvar - compile the (SET! var value) expression */
  272. XLOCAL do_setvar(form,cont)
  273. X  LVAL form; int cont;
  274. X{
  275. X    int lev,off;
  276. X    LVAL sym;
  277. X
  278. X    /* get the variable name */
  279. X    sym = car(form);
  280. X
  281. X    /* compile the value expression */
  282. X    form = cdr(form);
  283. X    if (atom(form))
  284. X    xlerror("expecting value expression",form);
  285. X    do_expr(car(form),C_NEXT);
  286. X
  287. X    /* set the variable value */
  288. X    if (findvariable(sym,&lev,&off))
  289. X    cd_evariable(OP_ESET,lev,off);
  290. X    else
  291. X    cd_variable(OP_GSET,sym);
  292. X    do_continuation(cont);
  293. X}
  294. X
  295. X/* do_quote - compile the (QUOTE ... ) expression */
  296. XLOCAL do_quote(form,cont)
  297. X  LVAL form; int cont;
  298. X{
  299. X    if (atom(form))
  300. X    xlerror("expecting quoted expression",form);
  301. X    do_literal(car(form),cont);
  302. X}
  303. X
  304. X/* do_lambda - compile the (LAMBDA ... ) expression */
  305. XLOCAL do_lambda(form,cont)
  306. X  LVAL form; int cont;
  307. X{
  308. X    if (atom(form))
  309. X    xlerror("expecting argument list",form);
  310. X    cd_fundefinition(NIL,car(form),cdr(form));
  311. X    do_continuation(cont);
  312. X}
  313. X
  314. X/* cd_fundefinition - compile the function */
  315. XLOCAL cd_fundefinition(fun,fargs,body)
  316. X  LVAL fun,fargs,body;
  317. X{
  318. X    int oldcbase;
  319. X
  320. X    /* establish a new environment frame */
  321. X    oldcbase = add_level();
  322. X
  323. X    /* compile the lambda list and the function body */
  324. X    parse_lambda_list(fargs,body);
  325. X    do_begin(body,C_RETURN);
  326. X
  327. X    /* build the code object */
  328. X    cpush(make_code_object(fun));
  329. X    
  330. X    /* restore the previous environment */
  331. X    remove_level(oldcbase);
  332. X
  333. X    /* compile code to create a closure */
  334. X    do_literal(pop(),C_NEXT);
  335. X    putcbyte(OP_CLOSE);
  336. X}
  337. X
  338. X/* parse_lambda_list - parse the formal argument list */
  339. XLOCAL parse_lambda_list(fargs,body)
  340. X  LVAL fargs,body;
  341. X{
  342. X    LVAL arg,restarg,new,last;
  343. X    int frame,slotn;
  344. X    
  345. X    /* setup the entry code */
  346. X    putcbyte(OP_FRAME);
  347. X    frame = putcbyte(0);
  348. X
  349. X    /* initialize the argument name list and slot number */
  350. X    restarg = last = NIL;
  351. X    slotn = 1;
  352. X    
  353. X    /* handle each required argument */
  354. X    while (consp(fargs) && (arg = car(fargs)) && !lambdakey(arg)) {
  355. X
  356. X    /* make sure the argument is a symbol */
  357. X    if (!symbolp(arg))
  358. X        xlerror("variable must be a symbol",arg);
  359. X
  360. X    /* add the argument name to the name list */
  361. X    new = cons(arg,NIL);
  362. X    if (last) rplacd(last,new);
  363. X    else setelement(car(car(info)),0,new);
  364. X    last = new;
  365. X
  366. X    /* generate an instruction to move the argument into the frame */
  367. X    putcbyte(OP_MVARG);
  368. X    putcbyte(slotn++);
  369. X    
  370. X    /* move the formal argument list pointer ahead */
  371. X    fargs = cdr(fargs);
  372. X    }
  373. X
  374. X    /* check for the '#!optional' argument */
  375. X    if (consp(fargs) && car(fargs) == lk_optional) {
  376. X    fargs = cdr(fargs);
  377. X
  378. X    /* handle each optional argument */
  379. X    while (consp(fargs) && (arg = car(fargs)) && !lambdakey(arg)) {
  380. X
  381. X        /* make sure the argument is a symbol */
  382. X        if (!symbolp(arg))
  383. X        xlerror("#!optional variable must be a symbol",arg);
  384. X
  385. X        /* add the argument name to the name list */
  386. X        new = cons(arg,NIL);
  387. X        if (last) rplacd(last,new);
  388. X        else setelement(car(car(info)),0,new);
  389. X        last = new;
  390. X
  391. X        /* move the argument into the frame */
  392. X        putcbyte(OP_MVOARG);
  393. X        putcbyte(slotn++);
  394. X    
  395. X        /* move the formal argument list pointer ahead */
  396. X        fargs = cdr(fargs);
  397. X    }
  398. X    }
  399. X
  400. X    /* check for the '#!rest' argument */
  401. X    if (consp(fargs) && car(fargs) == lk_rest) {
  402. X    fargs = cdr(fargs);
  403. X
  404. X    /* handle the rest argument */
  405. X    if (consp(fargs) && (restarg = car(fargs)) && !lambdakey(restarg)) {
  406. X
  407. X        /* make sure the argument is a symbol */
  408. X        if (!symbolp(restarg))
  409. X        xlerror("#!rest variable must be a symbol",restarg);
  410. X
  411. X        /* add the argument name to the name list */
  412. X        new = cons(restarg,NIL);
  413. X        if (last) rplacd(last,new);
  414. X        else setelement(car(car(info)),0,new);
  415. X        last = new;
  416. X
  417. X        /* make the #!rest argument list */
  418. X        putcbyte(OP_MVRARG);
  419. X        putcbyte(slotn++);
  420. X
  421. X        /* move the formal argument list pointer ahead */
  422. X        fargs = cdr(fargs);
  423. X    }
  424. X    else
  425. X        xlerror("expecting the #!rest variable");
  426. X    }
  427. X
  428. X    /* check for the a dotted tail */
  429. X    if (restarg == NIL && symbolp(fargs)) {
  430. X    restarg = fargs;
  431. X
  432. X    /* add the argument name to the name list */
  433. X    new = cons(restarg,NIL);
  434. X    if (last) rplacd(last,new);
  435. X    else setelement(car(car(info)),0,new);
  436. X    last = new;
  437. X
  438. X    /* make the #!rest argument list */
  439. X    putcbyte(OP_MVRARG);
  440. X    putcbyte(slotn++);
  441. X    fargs = NIL;
  442. X    }
  443. X
  444. X    /* check for the end of the argument list */
  445. X    if (fargs != NIL)
  446. X    xlerror("bad argument list tail",fargs);
  447. X
  448. X    /* make sure the user didn't supply too many arguments */
  449. X    if (restarg == NIL)
  450. X    putcbyte(OP_ALAST);
  451. X    
  452. X    /* scan the body for internal definitions */
  453. X    slotn += find_internal_definitions(body,last);
  454. X    
  455. X    /* fixup the frame instruction */
  456. X    cbuff[cbase+frame] = slotn;
  457. X}
  458. X
  459. X/* find_internal_definitions - find internal definitions */
  460. XLOCAL int find_internal_definitions(body,last)
  461. X  LVAL body,last;
  462. X{
  463. X    LVAL define,sym,new;
  464. X    int n=0;
  465. X
  466. X    /* look for all (define...) forms */
  467. X    for (define = xlenter("DEFINE"); consp(body); body = cdr(body))
  468. X    if (consp(car(body)) && car(car(body)) == define) {
  469. X        sym = cdr(car(body)); /* the rest of the (define...) form */
  470. X        if (consp(sym)) {     /* make sure there is a second subform */
  471. X        sym = car(sym);   /* get the second subform */
  472. X        while (consp(sym))/* check for a procedure definition */
  473. X            sym = car(sym);
  474. X        if (symbolp(sym)) {
  475. X            new = cons(sym,NIL);
  476. X            if (last) rplacd(last,new);
  477. X            else setelement(car(car(info)),0,new);
  478. X            last = new;
  479. X            ++n;
  480. X        }
  481. X        }
  482. X    }
  483. X    return (n);
  484. X}
  485. X
  486. X/* do_delay - compile the (DELAY ... ) expression */
  487. XLOCAL do_delay(form,cont)
  488. X  LVAL form; int cont;
  489. X{
  490. X    int oldcbase;
  491. X
  492. X    /* check argument list */
  493. X    if (atom(form))
  494. X    xlerror("expecting delay expression",form);
  495. X
  496. X    /* establish a new environment frame */
  497. X    oldcbase = add_level();
  498. X
  499. X    /* setup the entry code */
  500. X    putcbyte(OP_FRAME);
  501. X    putcbyte(1);
  502. X
  503. X    /* compile the expression */
  504. X    do_expr(car(form),C_RETURN);
  505. X
  506. X    /* build the code object */
  507. X    cpush(make_code_object(NIL));
  508. X    
  509. X    /* restore the previous environment */
  510. X    remove_level(oldcbase);
  511. X
  512. X    /* compile code to create a closure */
  513. X    do_literal(pop(),C_NEXT);
  514. X    putcbyte(OP_DELAY);
  515. X    do_continuation(cont);
  516. X}
  517. X
  518. X/* do_let - compile the (LET ... ) expression */
  519. XLOCAL do_let(form,cont)
  520. X  LVAL form; int cont;
  521. X{
  522. X    /* handle named let */
  523. X    if (consp(form) && symbolp(car(form)))
  524. X    do_named_let(form,cont);
  525. X    
  526. X    /* handle unnamed let */
  527. X    else
  528. X        cd_let(NIL,form,cont);
  529. X}
  530. X
  531. X/* do_named_let - compile the (LET name ... ) expression */
  532. XLOCAL do_named_let(form,cont)
  533. X  LVAL form; int cont;
  534. X{
  535. X    int oldcbase,nxt;
  536. X
  537. X    /* save a continuation */
  538. X    if (cont != C_RETURN) {
  539. X    putcbyte(OP_SAVE);
  540. X    nxt = putcword(0);
  541. X    }
  542. X    
  543. X    /* establish a new environment frame */
  544. X    oldcbase = add_level();
  545. X    setelement(car(car(info)),0,cons(car(form),NIL));
  546. X
  547. X    /* setup the entry code */
  548. X    putcbyte(OP_FRAME);
  549. X    putcbyte(2);
  550. X    
  551. X    /* compile the let expression */
  552. X    cd_let(car(form),cdr(form),C_RETURN);
  553. X
  554. X    /* build the code object */
  555. X    cpush(make_code_object(NIL));
  556. X    
  557. X    /* restore the previous environment */
  558. X    remove_level(oldcbase);
  559. X
  560. X    /* compile code to create a closure */
  561. X    do_literal(pop(),C_NEXT);
  562. X    putcbyte(OP_CLOSE);
  563. X
  564. X    /* apply the function */
  565. X    putcbyte(OP_CALL);
  566. X    putcbyte(1);
  567. X
  568. X    /* target for the continuation */
  569. X    if (cont != C_RETURN)
  570. X    fixup(nxt);
  571. X}
  572. X
  573. X/* cd_let - code a let expression */
  574. XLOCAL cd_let(name,form,cont)
  575. X  LVAL name,form; int cont;
  576. X{
  577. X    int oldcbase,nxt,lev,off,n;
  578. X
  579. X    /* make sure there is a binding list */
  580. X    if (atom(form) || !listp(car(form)))
  581. X    xlerror("expecting binding list",form);
  582. X
  583. X    /* save a continuation */
  584. X    if (cont != C_RETURN) {
  585. X    putcbyte(OP_SAVE);
  586. X    nxt = putcword(0);
  587. X    }
  588. X    
  589. X    /* push the initialization expressions */
  590. X    n = push_init_expressions(car(form));
  591. X
  592. X    /* establish a new environment frame */
  593. X    oldcbase = add_level();
  594. X
  595. X    /* compile the binding list */
  596. X    parse_let_variables(car(form),cdr(form));
  597. X
  598. X    /* compile the body of the let/letrec */
  599. X    do_begin(cdr(form),C_RETURN);
  600. X
  601. X    /* build the code object */
  602. X    cpush(make_code_object(NIL));
  603. X    
  604. X    /* restore the previous environment */
  605. X    remove_level(oldcbase);
  606. X
  607. X    /* compile code to create a closure */
  608. X    do_literal(pop(),C_NEXT);
  609. X    putcbyte(OP_CLOSE);
  610. X
  611. X    /* store the procedure */
  612. X    if (name && findvariable(name,&lev,&off))
  613. X    cd_evariable(OP_ESET,lev,off);
  614. X
  615. X    /* apply the function */
  616. X    putcbyte(OP_CALL);
  617. X    putcbyte(n);
  618. X
  619. X    /* target for the continuation */
  620. X    if (cont != C_RETURN)
  621. X    fixup(nxt);
  622. X}
  623. X
  624. X/* do_letrec - compile the (LETREC ... ) expression */
  625. XLOCAL do_letrec(form,cont)
  626. X  LVAL form; int cont;
  627. X{
  628. X    int oldcbase,nxt,n;
  629. X
  630. X    /* make sure there is a binding list */
  631. X    if (atom(form) || !listp(car(form)))
  632. X    xlerror("expecting binding list",form);
  633. X
  634. X    /* save a continuation */
  635. X    if (cont != C_RETURN) {
  636. X    putcbyte(OP_SAVE);
  637. X    nxt = putcword(0);
  638. X    }
  639. X    
  640. X    /* push the initialization expressions */
  641. X    n = push_dummy_values(car(form));
  642. X
  643. X    /* establish a new environment frame */
  644. X    oldcbase = add_level();
  645. X
  646. X    /* compile the binding list */
  647. X    parse_let_variables(car(form),cdr(form));
  648. X
  649. X    /* compile instructions to set the bound variables */
  650. X    set_bound_variables(car(form));
  651. X    
  652. X    /* compile the body of the let/letrec */
  653. X    do_begin(cdr(form),C_RETURN);
  654. X
  655. X    /* build the code object */
  656. X    cpush(make_code_object(NIL));
  657. X    
  658. X    /* restore the previous environment */
  659. X    remove_level(oldcbase);
  660. X
  661. X    /* compile code to create a closure */
  662. X    do_literal(pop(),C_NEXT);
  663. X    putcbyte(OP_CLOSE);
  664. X
  665. X    /* apply the function */
  666. X    putcbyte(OP_CALL);
  667. X    putcbyte(n);
  668. X
  669. X    /* target for the continuation */
  670. X    if (cont != C_RETURN)
  671. X    fixup(nxt);
  672. X}
  673. X
  674. X/* do_letstar - compile the (LET* ... ) expression */
  675. XLOCAL do_letstar(form,cont)
  676. X  LVAL form; int cont;
  677. X{
  678. X    int nxt;
  679. X    
  680. X    /* make sure there is a binding list */
  681. X    if (atom(form) || !listp(car(form)))
  682. X    xlerror("expecting binding list",form);
  683. X
  684. X    /* handle the case where there are bindings */
  685. X    if (consp(car(form))) {
  686. X    
  687. X    /* save a continuation */
  688. X    if (cont != C_RETURN) {
  689. X        putcbyte(OP_SAVE);
  690. X        nxt = putcword(0);
  691. X    }
  692. X    
  693. X    /* build the nested lambda expressions */
  694. X    letstar1(car(form),cdr(form));
  695. X    
  696. X    /* target for the continuation */
  697. X    if (cont != C_RETURN)
  698. X        fixup(nxt);
  699. X    }
  700. X    
  701. X    /* handle the case where there are no bindings */
  702. X    else
  703. X    do_begin(cdr(form),cont);
  704. X}
  705. X
  706. X/* letstar1 - helper routine for let* */
  707. XLOCAL letstar1(blist,body)
  708. X  LVAL blist,body;
  709. X{
  710. X    int oldcbase,n;
  711. X
  712. X    /* push the next initialization expressions */
  713. X    cpush(cons(car(blist),NIL));
  714. X    n = push_init_expressions(top());
  715. X
  716. X    /* establish a new environment frame */
  717. X    oldcbase = add_level();
  718. X
  719. X    /* handle the case where there are more bindings */
  720. X    if (consp(cdr(blist))) {
  721. X    parse_let_variables(top(),NIL);
  722. X    letstar1(cdr(blist),body);
  723. X    }
  724. X    
  725. X    /* handle the last binding */
  726. X    else {
  727. X    parse_let_variables(top(),body);
  728. X    do_begin(body,C_RETURN);
  729. X    }
  730. X    
  731. X    /* build the code object */
  732. X    settop(make_code_object(NIL));
  733. X    
  734. X    /* restore the previous environment */
  735. X    remove_level(oldcbase);
  736. X
  737. X    /* compile code to create a closure */
  738. X    do_literal(pop(),C_NEXT);
  739. X    putcbyte(OP_CLOSE);
  740. X
  741. X    /* apply the function */
  742. X    putcbyte(OP_CALL);
  743. X    putcbyte(n);
  744. X}
  745. X
  746. X/* push_dummy_values - push dummy values for a 'letrec' expression */
  747. XLOCAL int push_dummy_values(blist)
  748. X  LVAL blist;
  749. X{
  750. X    int n=0;
  751. X    if (consp(blist)) {
  752. X    putcbyte(OP_NIL);
  753. X    for (; consp(blist); blist = cdr(blist), ++n)
  754. X        putcbyte(OP_PUSH);
  755. X    }
  756. X    return (n);
  757. X}
  758. X
  759. X/* push_init_expressions - push init expressions for a 'let' expression */
  760. XLOCAL int push_init_expressions(blist)
  761. X  LVAL blist;
  762. X{
  763. X    int n;
  764. X    if (consp(blist)) {
  765. X    n = push_init_expressions(cdr(blist));
  766. X    if (consp(car(blist)) && consp(cdr(car(blist))))
  767. X        do_expr(car(cdr(car(blist))),C_NEXT);
  768. X    else
  769. X        putcbyte(OP_NIL);
  770. X    putcbyte(OP_PUSH);
  771. X    return (n+1);
  772. X    }
  773. X    return (0);
  774. X}
  775. X
  776. X/* parse_let_variables - parse the binding list */
  777. XLOCAL parse_let_variables(blist,body)
  778. X  LVAL blist,body;
  779. X{
  780. X    LVAL arg,new,last;
  781. X    int frame,slotn;
  782. X    
  783. X    /* setup the entry code */
  784. X    putcbyte(OP_FRAME);
  785. X    frame = putcbyte(0);
  786. X
  787. X    /* initialize the argument name list and slot number */
  788. X    last = NIL;
  789. X    slotn = 1;
  790. X    
  791. X    /* handle each required argument */
  792. X    while (consp(blist) && (arg = car(blist))) {
  793. X
  794. X    /* make sure the argument is a symbol */
  795. X    if (symbolp(arg))
  796. X        new = cons(arg,NIL);
  797. X    else if (consp(arg) && symbolp(car(arg)))
  798. X        new = cons(car(arg),NIL);
  799. X    else
  800. X        xlerror("invalid binding",arg);
  801. X
  802. X    /* add the argument name to the name list */
  803. X    if (last) rplacd(last,new);
  804. X    else setelement(car(car(info)),0,new);
  805. X    last = new;
  806. X
  807. X    /* generate an instruction to move the argument into the frame */
  808. X    putcbyte(OP_MVARG);
  809. X    putcbyte(slotn++);
  810. X    
  811. X    /* move the formal argument list pointer ahead */
  812. X    blist = cdr(blist);
  813. X    }
  814. X    putcbyte(OP_ALAST);
  815. X
  816. X    /* scan the body for internal definitions */
  817. X    slotn += find_internal_definitions(body,last);
  818. X    
  819. X    /* fixup the frame instruction */
  820. X    cbuff[cbase+frame] = slotn;
  821. X}
  822. X
  823. X/* set_bound_variables - set bound variables in a 'letrec' expression */
  824. XLOCAL set_bound_variables(blist)
  825. X  LVAL blist;
  826. X{
  827. X    int lev,off;
  828. X    for (; consp(blist); blist = cdr(blist)) {
  829. X    if (consp(car(blist)) && consp(cdr(car(blist)))) {
  830. X        do_expr(car(cdr(car(blist))),C_NEXT);
  831. X        if (findvariable(car(car(blist)),&lev,&off))
  832. X        cd_evariable(OP_ESET,lev,off);
  833. X        else
  834. X        xlerror("compiler error -- can't find",car(car(blist)));
  835. X    }
  836. X    }
  837. X}
  838. X
  839. X/* make_code_object - build a code object */
  840. XLOCAL LVAL make_code_object(fun)
  841. X  LVAL fun;
  842. X{
  843. X    unsigned char *cp;
  844. X    LVAL code,p;
  845. X    int i;
  846. X
  847. X    /* create a code object */
  848. X    code = newcode(FIRSTLIT + length(car(cdr(info)))); cpush(code);
  849. X    setbcode(code,newstring(cptr - cbase));
  850. X    setcname(code,fun);                        /* function name */
  851. X    setvnames(code,getelement(car(car(info)),0));/* lambda list variables */
  852. X
  853. X    /* copy the literals into the code object */
  854. X    for (i = FIRSTLIT, p = car(cdr(info)); consp(p); p = cdr(p), ++i)
  855. X    setelement(code,i,car(p));
  856. X
  857. X    /* copy the byte codes */
  858. X    for (i = cbase, cp = getstring(getbcode(code)); i < cptr; )
  859. X    *cp++ = cbuff[i++];
  860. X
  861. X    /* return the new code object */
  862. X    return (pop());
  863. X}
  864. X
  865. X/* do_cond - compile the (COND ... ) expression */
  866. XLOCAL do_cond(form,cont)
  867. X  LVAL form; int cont;
  868. X{
  869. X    int nxt,end;
  870. X    if (consp(form)) {
  871. X    for (end = 0; consp(form); form = cdr(form)) {
  872. X        if (atom(car(form)))
  873. X        xlerror("expecting a cond clause",form);
  874. X        do_expr(car(car(form)),C_NEXT);
  875. X        putcbyte(OP_BRF);
  876. X        nxt = putcword(0);
  877. X        if (cdr(car(form)))
  878. X        do_begin(cdr(car(form)),cont);
  879. X        else
  880. X        do_continuation(cont);
  881. X        if (cont == C_NEXT) {
  882. X        putcbyte(OP_BR);
  883. X        end = putcword(end);
  884. X        }
  885. X        fixup(nxt);
  886. X    }
  887. X    fixup(end);
  888. X    }
  889. X    else
  890. X    putcbyte(OP_NIL);
  891. X    do_continuation(cont);
  892. X}
  893. X
  894. X/* do_and - compile the (AND ... ) expression */
  895. XLOCAL do_and(form,cont)
  896. X  LVAL form; int cont;
  897. X{
  898. X    int end;
  899. X    if (consp(form)) {
  900. X    for (end = 0; consp(form); form = cdr(form)) {
  901. X        if (cdr(form)) {
  902. X        do_expr(car(form),C_NEXT);
  903. X        putcbyte(OP_BRF);
  904. X        end = putcword(end);
  905. X        }
  906. X        else
  907. X        do_expr(car(form),cont);
  908. X    }
  909. X    fixup(end);
  910. X    }
  911. X    else
  912. X    putcbyte(OP_T);
  913. X    do_continuation(cont);
  914. X}
  915. X
  916. X/* do_or - compile the (OR ... ) expression */
  917. XLOCAL do_or(form,cont)
  918. X  LVAL form; int cont;
  919. X{
  920. X    int end;
  921. X    if (consp(form)) {
  922. X    for (end = 0; consp(form); form = cdr(form)) {
  923. X        if (cdr(form)) {
  924. X        do_expr(car(form),C_NEXT);
  925. X        putcbyte(OP_BRT);
  926. X        end = putcword(end);
  927. X        }
  928. X        else
  929. X        do_expr(car(form),cont);
  930. X    }
  931. X    fixup(end);
  932. X    }
  933. X    else
  934. X    putcbyte(OP_NIL);
  935. X    do_continuation(cont);
  936. X}
  937. X
  938. X/* do_if - compile the (IF ... ) expression */
  939. XLOCAL do_if(form,cont)
  940. X  LVAL form; int cont;
  941. X{
  942. X    int nxt,end;
  943. X
  944. X    /* compile the test expression */
  945. X    if (atom(form))
  946. X    xlerror("expecting test expression",form);
  947. X    do_expr(car(form),C_NEXT);
  948. X
  949. X    /* skip around the 'then' clause if the expression is false */
  950. X    putcbyte(OP_BRF);
  951. X    nxt = putcword(0);
  952. X
  953. X    /* skip to the 'then' clause */
  954. X    form = cdr(form);
  955. X    if (atom(form))
  956. X    xlerror("expecting then clause",form);
  957. X
  958. X    /* compile the 'then' and 'else' clauses */
  959. X    if (consp(cdr(form))) {
  960. X    if (cont == C_NEXT) {
  961. X        do_expr(car(form),C_NEXT);
  962. X        putcbyte(OP_BR);
  963. X        end = putcword(0);
  964. X    }
  965. X    else {
  966. X        do_expr(car(form),cont);
  967. X        end = -1;
  968. X    }
  969. X    fixup(nxt);
  970. X    do_expr(car(cdr(form)),cont);
  971. X    nxt = end;
  972. X    }
  973. X
  974. X    /* compile just a 'then' clause */
  975. X    else
  976. X    do_expr(car(form),cont);
  977. X
  978. X    /* handle the end of the statement */
  979. X    if (nxt >= 0) {
  980. X    fixup(nxt);
  981. X    do_continuation(cont);
  982. X    }
  983. X}
  984. X
  985. X/* do_begin - compile the (BEGIN ... ) expression */
  986. XLOCAL do_begin(form,cont)
  987. X  LVAL form; int cont;
  988. X{
  989. X    if (consp(form))
  990. X    for (; consp(form); form = cdr(form))
  991. X        if (consp(cdr(form)))
  992. X        do_expr(car(form),C_NEXT);
  993. X        else
  994. X        do_expr(car(form),cont);
  995. X    else {
  996. X    putcbyte(OP_NIL);
  997. X    do_continuation(cont);
  998. X    }
  999. X}
  1000. X
  1001. X/* do_while - compile the (WHILE ... ) expression */
  1002. XLOCAL do_while(form,cont)
  1003. X  LVAL form; int cont;
  1004. X{
  1005. X    int loop,nxt;
  1006. X
  1007. X    /* make sure there is a test expression */
  1008. X    if (atom(form))
  1009. X    xlerror("expecting test expression",form);
  1010. X
  1011. X    /* skip around the 'body' to the test expression */
  1012. X    putcbyte(OP_BR);
  1013. X    nxt = putcword(0);
  1014. X
  1015. X    /* compile the loop body */
  1016. X    loop = cptr - cbase;
  1017. X    do_begin(cdr(form),C_NEXT);
  1018. X
  1019. X    /* label for the first iteration */
  1020. X    fixup(nxt);
  1021. X
  1022. X    /* compile the test expression */
  1023. X    nxt = cptr - cbase;
  1024. X    do_expr(car(form),C_NEXT);
  1025. X
  1026. X    /* skip around the 'body' if the expression is false */
  1027. X    putcbyte(OP_BRT);
  1028. X    putcword(loop);
  1029. X
  1030. X    /* compile the continuation */
  1031. X    do_continuation(cont);
  1032. X}
  1033. X
  1034. X/* do_access - compile the (ACCESS var env) expression */
  1035. XLOCAL do_access(form,cont)
  1036. X  LVAL form; int cont;
  1037. X{
  1038. X    LVAL sym;
  1039. X
  1040. X    /* get the variable name */
  1041. X    if (atom(form) || !symbolp(car(form)))
  1042. X    xlerror("expecting symbol",form);
  1043. X    sym = car(form);
  1044. X
  1045. X    /* compile the environment expression */
  1046. X    form = cdr(form);
  1047. X    if (atom(form))
  1048. X    xlerror("expecting environment expression",form);
  1049. X    do_expr(car(form),C_NEXT);
  1050. X
  1051. X    /* get the variable value */
  1052. X    cd_variable(OP_AREF,sym);
  1053. X    do_continuation(cont);
  1054. X}
  1055. X
  1056. X/* do_setaccess - compile the (SET! (ACCESS var env) value) expression */
  1057. XLOCAL do_setaccess(form,cont)
  1058. X  LVAL form; int cont;
  1059. X{
  1060. X    LVAL aform,sym;
  1061. X
  1062. X    /* make sure this is an access form */
  1063. X    aform = car(form);
  1064. X    if (atom(aform) || car(aform) != xlenter("ACCESS"))
  1065. X    xlerror("expecting an ACCESS form",aform);
  1066. X
  1067. X    /* get the variable name */
  1068. X    aform = cdr(aform);
  1069. X    if (atom(aform) || !symbolp(car(aform)))
  1070. X    xlerror("expecting symbol",aform);
  1071. X    sym = car(aform);
  1072. X
  1073. X    /* compile the environment expression */
  1074. X    aform = cdr(aform);
  1075. X    if (atom(aform))
  1076. X    xlerror("expecting environment expression",aform);
  1077. X    do_expr(car(aform),C_NEXT);
  1078. X    putcbyte(OP_PUSH);
  1079. X
  1080. X    /* compile the value expression */
  1081. X    form = cdr(form);
  1082. X    if (atom(form))
  1083. X    xlerror("expecting value expression",form);
  1084. X    do_expr(car(form),C_NEXT);
  1085. X
  1086. X    /* set the variable value */
  1087. X    cd_variable(OP_ASET,sym);
  1088. X    do_continuation(cont);
  1089. X}
  1090. X
  1091. X/* do_call - compile a function call */
  1092. XLOCAL do_call(form,cont)
  1093. X  LVAL form; int cont;
  1094. X{
  1095. X    int nxt,n;
  1096. X    
  1097. X    /* save a continuation */
  1098. X    if (cont != C_RETURN) {
  1099. X    putcbyte(OP_SAVE);
  1100. X    nxt = putcword(0);
  1101. X    }
  1102. X    
  1103. X    /* compile each argument expression */
  1104. X    n = push_args(cdr(form));
  1105. X
  1106. X    /* compile the function itself */
  1107. X    do_expr(car(form),C_NEXT);
  1108. X
  1109. X    /* apply the function */
  1110. X    putcbyte(OP_CALL);
  1111. X    putcbyte(n);
  1112. X
  1113. X    /* target for the continuation */
  1114. X    if (cont != C_RETURN)
  1115. X    fixup(nxt);
  1116. X}
  1117. X
  1118. X/* push_args - compile the arguments for a function call */
  1119. XLOCAL int push_args(form)
  1120. X  LVAL form;
  1121. X{
  1122. X    int n;
  1123. X    if (consp(form)) {
  1124. X    n = push_args(cdr(form));
  1125. X    do_expr(car(form),C_NEXT);
  1126. X    putcbyte(OP_PUSH);
  1127. X    return (n+1);
  1128. X    }
  1129. X    return (0);
  1130. X}
  1131. X
  1132. X/* do_nary - compile nary operator expressions */
  1133. XLOCAL do_nary(op,n,form,cont)
  1134. X  int op,n; LVAL form; int cont;
  1135. X{
  1136. X    if (n < 0 && (n = (-n)) != length(cdr(form)))
  1137. X    do_call(form,cont);
  1138. X    else {
  1139. X    push_nargs(cdr(form),n);
  1140. X    putcbyte(op);
  1141. X    do_continuation(cont);
  1142. X    }
  1143. X}
  1144. X
  1145. X/* push_nargs - compile the arguments for an inline function call */
  1146. XLOCAL int push_nargs(form,n)
  1147. X  LVAL form; int n;
  1148. X{
  1149. X    if (consp(form)) {
  1150. X    if (n == 0)
  1151. X        xlerror("too many arguments",form);
  1152. X    if (push_nargs(cdr(form),n-1))
  1153. X        putcbyte(OP_PUSH);
  1154. X    do_expr(car(form),C_NEXT);
  1155. X    return (TRUE);
  1156. X    }
  1157. X    if (n)
  1158. X    xlerror("too few arguments",form);
  1159. X    return (FALSE);
  1160. X}
  1161. X
  1162. X/* do_literal - compile a literal */
  1163. XLOCAL do_literal(lit,cont)
  1164. X  LVAL lit; int cont;
  1165. X{
  1166. X    cd_literal(lit);
  1167. X    do_continuation(cont);
  1168. X}
  1169. X
  1170. X/* do_identifier - compile an identifier */
  1171. XLOCAL do_identifier(sym,cont)
  1172. X  LVAL sym; int cont;
  1173. X{
  1174. X    int lev,off;
  1175. X    if (sym == true)
  1176. X    putcbyte(OP_T);
  1177. X    else if (findvariable(sym,&lev,&off))
  1178. X    cd_evariable(OP_EREF,lev,off);
  1179. X    else
  1180. X    cd_variable(OP_GREF,sym);
  1181. X    do_continuation(cont);
  1182. X}
  1183. X
  1184. X/* do_continuation - compile a continuation */
  1185. XLOCAL do_continuation(cont)
  1186. X  int cont;
  1187. X{
  1188. X    switch (cont) {
  1189. X    case C_RETURN:
  1190. X    putcbyte(OP_RETURN);
  1191. X    break;
  1192. X    case C_NEXT:
  1193. X    break;
  1194. X    }
  1195. X}
  1196. X
  1197. X/* add_level - add a nesting level */
  1198. XLOCAL int add_level()
  1199. X{
  1200. X    int oldcbase;
  1201. X    
  1202. X    /* establish a new environment frame */
  1203. X    rplaca(info,newframe(car(info),1));
  1204. X    rplacd(info,cons(NIL,cdr(info)));
  1205. X
  1206. X    /* setup the base of the code for this function */
  1207. X    oldcbase = cbase;
  1208. X    cbase = cptr;
  1209. X
  1210. X    /* return the old code base */
  1211. X    return (oldcbase);
  1212. X}
  1213. X
  1214. X/* remove_level - remove a nesting level */
  1215. XLOCAL remove_level(oldcbase)
  1216. X  int oldcbase;
  1217. X{
  1218. X    /* restore the previous environment */
  1219. X    rplaca(info,cdr(car(info)));
  1220. X    rplacd(info,cdr(cdr(info)));
  1221. X
  1222. X    /* restore the base and code pointer */
  1223. X    cptr = cbase;
  1224. X    cbase = oldcbase;
  1225. X}
  1226. X
  1227. X/* findvariable - find an environment variable */
  1228. XLOCAL int findvariable(sym,plev,poff)
  1229. X  LVAL sym; int *plev,*poff;
  1230. X{
  1231. X    int lev,off;
  1232. X    LVAL e,a;
  1233. X    for (e = car(info), lev = 0; envp(e); e = cdr(e), ++lev)
  1234. X    for (a = getelement(car(e),0), off = 1; consp(a); a = cdr(a), ++off)
  1235. X        if (sym == car(a)) {
  1236. X        *plev = lev;
  1237. X        *poff = off;
  1238. X        return (TRUE);
  1239. X        }
  1240. X    return (FALSE);
  1241. X}
  1242. X
  1243. X/* findcvariable - find an environment variable in the current frame */
  1244. XLOCAL int findcvariable(sym,poff)
  1245. X  LVAL sym; int *poff;
  1246. X{
  1247. X    int off;
  1248. X    LVAL a;
  1249. X    a = getelement(car(car(info)),0);
  1250. X    for (off = 1; consp(a); a = cdr(a), ++off)
  1251. X    if (sym == car(a)) {
  1252. X        *poff = off;
  1253. X        return (TRUE);
  1254. X    }
  1255. X    return (FALSE);
  1256. X}
  1257. X
  1258. X/* findliteral - find a literal in the literal frame */
  1259. XLOCAL int findliteral(lit)
  1260. X  LVAL lit;
  1261. X{
  1262. X    int o = FIRSTLIT;
  1263. X    LVAL t,p;
  1264. X    if (t = car(cdr(info))) {
  1265. X    for (p = NIL; consp(t); p = t, t = cdr(t), ++o)
  1266. X        if (equal(lit,car(t)))
  1267. X        return (o);
  1268. X    rplacd(p,cons(lit,NIL));
  1269. X    }
  1270. X    else
  1271. X    rplaca(cdr(info),cons(lit,NIL));
  1272. X    return (o);
  1273. X}
  1274. X
  1275. X/* cd_variable - compile a variable reference */
  1276. XLOCAL cd_variable(op,sym)
  1277. X  int op; LVAL sym;
  1278. X{
  1279. X    putcbyte(op);
  1280. X    putcbyte(findliteral(sym));
  1281. X}
  1282. X
  1283. X/* cd_evariable - compile an environment variable reference */
  1284. XLOCAL cd_evariable(op,lev,off)
  1285. X  int op,lev,off;      
  1286. X{
  1287. X    putcbyte(op);
  1288. X    putcbyte(lev);
  1289. X    putcbyte(off);
  1290. X}
  1291. X
  1292. X/* cd_literal - compile a literal reference */
  1293. XLOCAL cd_literal(lit)
  1294. X  LVAL lit;
  1295. X{
  1296. X    if (lit == NIL)
  1297. X    putcbyte(OP_NIL);
  1298. X    else if (lit == true)
  1299. X    putcbyte(OP_T);
  1300. X    else {
  1301. X    putcbyte(OP_LIT);
  1302. X    putcbyte(findliteral(lit));
  1303. X    }
  1304. X}
  1305. X
  1306. X/* putcbyte - put a code byte into data space */
  1307. XLOCAL int putcbyte(b)
  1308. X  int b;
  1309. X{
  1310. X    int adr;
  1311. X    if (cptr >= CMAX)
  1312. X    xlabort("insufficient code space");
  1313. X    adr = (cptr - cbase);
  1314. X    cbuff[cptr++] = b;
  1315. X    return (adr);
  1316. X}
  1317. X
  1318. X/* putcword - put a code word into data space */
  1319. XLOCAL int putcword(w)
  1320. X  int w;
  1321. X{
  1322. X    int adr;
  1323. X    adr = putcbyte(w >> 8);
  1324. X    putcbyte(w);
  1325. X    return (adr);
  1326. X}
  1327. X
  1328. X/* fixup - fixup a reference chain */
  1329. XLOCAL fixup(chn)
  1330. X  int chn;
  1331. X{
  1332. X    int val,hval,nxt;
  1333. X
  1334. X    /* store the value into each location in the chain */
  1335. X    val = cptr - cbase; hval = val >> 8;
  1336. X    for (; chn; chn = nxt) {
  1337. X    nxt = (cbuff[cbase+chn] << 8) | (cbuff[cbase+chn+1]);
  1338. X    cbuff[cbase+chn] = hval;
  1339. X    cbuff[cbase+chn+1] = val;
  1340. X    }
  1341. X}
  1342. X
  1343. X/* length - find the length of a list */
  1344. Xint length(list)
  1345. X  LVAL list;
  1346. X{
  1347. X    int len;
  1348. X    for (len = 0; consp(list); list = cdr(list))
  1349. X    ++len;
  1350. X    return (len);
  1351. X}
  1352. X
  1353. X/* instruction output formats */
  1354. X#define FMT_NONE    0
  1355. X#define FMT_BYTE    1
  1356. X#define FMT_LOFF    2
  1357. X#define FMT_WORD    3
  1358. X#define FMT_EOFF    4
  1359. X
  1360. Xtypedef struct { int ot_code; char *ot_name; int ot_fmt; } OTDEF;
  1361. XOTDEF otab[] = {
  1362. X{    OP_BRT,        "BRT",        FMT_WORD    },
  1363. X{    OP_BRF,        "BRF",        FMT_WORD    },
  1364. X{    OP_BR,        "BR",        FMT_WORD    },
  1365. X{    OP_LIT,        "LIT",        FMT_LOFF    },
  1366. X{    OP_GREF,    "GREF",        FMT_LOFF    },
  1367. X{    OP_GSET,    "GSET",        FMT_LOFF    },
  1368. X{    OP_EREF,    "EREF",        FMT_EOFF    },
  1369. X{    OP_ESET,    "ESET",        FMT_EOFF    },
  1370. X{    OP_SAVE,    "SAVE",        FMT_WORD    },
  1371. X{    OP_CALL,    "CALL",        FMT_BYTE    },
  1372. X{    OP_RETURN,    "RETURN",    FMT_NONE    },
  1373. X{    OP_T,        "T",        FMT_NONE    },
  1374. X{    OP_NIL,        "NIL",        FMT_NONE    },
  1375. X{    OP_PUSH,    "PUSH",        FMT_NONE    },
  1376. X{    OP_CLOSE,    "CLOSE",    FMT_NONE    },
  1377. X{    OP_DELAY,    "DELAY",    FMT_NONE    },
  1378. X
  1379. X{    OP_FRAME,    "FRAME",    FMT_BYTE    },
  1380. X{    OP_MVARG,    "MVARG",    FMT_BYTE    },
  1381. X{    OP_MVOARG,    "MVOARG",    FMT_BYTE    },
  1382. X{    OP_MVRARG,    "MVRARG",    FMT_BYTE    },
  1383. X{    OP_ADROP,    "ADROP",    FMT_NONE    },
  1384. X{    OP_ALAST,    "ALAST",    FMT_NONE    },
  1385. X
  1386. X{    OP_AREF,    "AREF",        FMT_LOFF    },
  1387. X{    OP_ASET,    "ASET",        FMT_LOFF    },
  1388. X
  1389. X{0,0,0}
  1390. X};
  1391. X
  1392. X/* decode_procedure - decode the instructions in a code object */
  1393. Xdecode_procedure(fptr,fun)
  1394. X  LVAL fptr,fun;
  1395. X{
  1396. X    int len,lc,n;
  1397. X    LVAL code,env;
  1398. X    code = getcode(fun);
  1399. X    env = getenv(fun);
  1400. X    len = getslength(getbcode(code));
  1401. X    for (lc = 0; lc < len; lc += n)
  1402. X    n = decode_instruction(fptr,code,lc,env);
  1403. X}
  1404. X
  1405. X/* decode_instruction - decode a single bytecode instruction */
  1406. Xint decode_instruction(fptr,code,lc,env)
  1407. X  LVAL fptr,code; int lc; LVAL env;
  1408. X{
  1409. X    unsigned char *cp;
  1410. X    char buf[100];
  1411. X    OTDEF *op;
  1412. X    NTDEF *np;
  1413. X    int i,n=1;
  1414. X    LVAL tmp;
  1415. X
  1416. X    /* get a pointer to the bytecodes for this instruction */
  1417. X    cp = getstring(getbcode(code)) + lc;
  1418. X
  1419. X    /* show the address and opcode */
  1420. X    if (tmp = getcname(code))
  1421. X    sprintf(buf,"%s:%04x %02x ",getstring(getpname(tmp)),lc,*cp);
  1422. X    else {
  1423. X    sprintf(buf,AFMT,code); xlputstr(fptr,buf);
  1424. X        sprintf(buf,":%04x %02x ",lc,*cp);
  1425. X    }
  1426. X    xlputstr(fptr,buf);
  1427. X
  1428. X    /* display the operands */
  1429. X    for (op = otab; op->ot_name; ++op)
  1430. X    if (*cp == op->ot_code) {
  1431. X        switch (op->ot_fmt) {
  1432. X        case FMT_NONE:
  1433. X        sprintf(buf,"      %s\n",op->ot_name);
  1434. X        xlputstr(fptr,buf);
  1435. X        break;
  1436. X        case FMT_BYTE:
  1437. X        sprintf(buf,"%02x    %s %02x\n",cp[1],op->ot_name,cp[1]);
  1438. X        xlputstr(fptr,buf);
  1439. X        n += 1;
  1440. X        break;
  1441. X        case FMT_LOFF:
  1442. X        sprintf(buf,"%02x    %s %02x ; ",cp[1],op->ot_name,cp[1]);
  1443. X        xlputstr(fptr,buf);
  1444. X        xlprin1(getelement(code,cp[1]),fptr);
  1445. X        xlterpri(fptr);
  1446. X        n += 1;
  1447. X        break;
  1448. X        case FMT_WORD:
  1449. X        sprintf(buf,"%02x %02x %s %02x%02x\n",cp[1],cp[2],
  1450. X            op->ot_name,cp[1],cp[2]);
  1451. X        xlputstr(fptr,buf);
  1452. X        n += 2;
  1453. X        break;
  1454. X        case FMT_EOFF:
  1455. X        if ((i = cp[1]) == 0)
  1456. X            tmp = getvnames(code);
  1457. X        else {
  1458. X            for (tmp = env; i > 1; --i) tmp = cdr(tmp);
  1459. X            tmp = getelement(car(tmp),0);
  1460. X        }
  1461. X        for (i = cp[2]; i > 1; --i) tmp = cdr(tmp);
  1462. X        sprintf(buf,"%02x %02x %s %02x %02x ; ",cp[1],cp[2],
  1463. X            op->ot_name,cp[1],cp[2]);
  1464. X        xlputstr(fptr,buf);
  1465. X        xlprin1(car(tmp),fptr);
  1466. X        xlterpri(fptr);
  1467. X        n += 2;
  1468. X        break;
  1469. X        }
  1470. X        return (n);
  1471. X    }
  1472. X    
  1473. X    /* check for an integrable function */
  1474. X    for (np = ntab; np->nt_name; ++np)
  1475. X    if (*cp == np->nt_code) {
  1476. X        sprintf(buf,"      %s\n",np->nt_name);
  1477. X        xlputstr(fptr,buf);
  1478. X        return (n);
  1479. X    }
  1480. X
  1481. X    /* unknown opcode */
  1482. X    sprintf(buf,"      <UNKNOWN>\n");
  1483. X    xlputstr(fptr,buf);
  1484. X    return (n);
  1485. X}
  1486. END_OF_FILE
  1487. if test 33402 -ne `wc -c <'Src/xscom.c'`; then
  1488.     echo shar: \"'Src/xscom.c'\" unpacked with wrong size!
  1489. fi
  1490. # end of 'Src/xscom.c'
  1491. fi
  1492. echo shar: End of archive 5 \(of 7\).
  1493. cp /dev/null ark5isdone
  1494. MISSING=""
  1495. for I in 1 2 3 4 5 6 7 ; do
  1496.     if test ! -f ark${I}isdone ; then
  1497.     MISSING="${MISSING} ${I}"
  1498.     fi
  1499. done
  1500. if test "${MISSING}" = "" ; then
  1501.     echo You have unpacked all 7 archives.
  1502.     rm -f ark[1-9]isdone
  1503. else
  1504.     echo You still need to unpack the following archives:
  1505.     echo "        " ${MISSING}
  1506. fi
  1507. ##  End of shell archive.
  1508. exit 0
  1509. -- 
  1510. Mail submissions (sources or binaries) to <amiga@cs.odu.edu>.
  1511. Mail comments to the moderator at <amiga-request@cs.odu.edu>.
  1512. Post requests for sources, and general discussion to comp.sys.amiga.
  1513.